//
//  Class.h
//  面试题
//
//  Created by Toj on 8/11/21.
//

https://www.jianshu.com/p/941e20fb001d
https://www.jianshu.com/p/5429b451bca0

#pragma mark - 问题?
1. 类是什么?
2. initialize 与 load 方法的作用
3. initialize 与 load 什么时候被调用的
4. initialize 与 load 特点
5. 类的底层实现

#pragma mark initialize 与 load 方法的作用
OBJC_PRINT_LOAD_METHODS:
打印出项目中所有load方法的调用，可以方便开发中监控load方法数量
 (load方法是会影响启动速度)

load: 当类被引用进项目的时候(runtime启动加到内存)就会执行load函数(在main函数开始执行之前),
与这个类是否被用到无关, 每个类的load函数只会自动调用一次.
由于load函数是系统自动加载的, 因此不需要调用父类的load函数, 否则父类的load函数会多次执行.

当类(Class)或者类别(Category)加入Runtime中时(就是被引用的时候).
实现该方法, 可以在加载时做一些类特有的操作.

调用所有的Framework中的初始化方法
调用所有的+load方法
调用C++的静态初始化方及C/C++中的attribute(constructor)函数
调用所有链接到目标文件的framework中的初始化方法

一个类的+load方法在其父类的+load方法后调用
一个Category的+load方法在被其扩展的类的自有+load方法后调用
在+load方法中，可以安全地向同一二进制包中的其它无关的类发送消息，但接收消息的类中的+load方法可能尚未被调用。

initialize:
initialize在类或者其子类的第一个方法被调用前调用.
即使类文件被引用进项目, 但是没有使用, initialize不会被调用.
由于是系统自动调用, 也不需要再调用 [super initialize],否则父类的initialize会被多次执行.
假如这个类放到代码中, 而这段代码并没有被执行, 这个函数是不会被执行的.

Runtime在一个程序中每一个类的一个程序中发送一个初始化一次,
或是从它继承的任何类中, 都是在程序中发送第一条消息. (因此, 当该类不使用时, 该方法可能永远不会被调用)运行时发送一个线程安全的方式初始化消息.
父类的调用一定在子类之前.

#pragma mark initialize 与 load 什么时候被调用的
load:
当类(Class)或者类别(Category)加入Runtime中时(就是被引用的时候).

initialize:
在类或者其子类的第一个方法被调用前调用

#pragma mark initialize 与 load 特点
load函数调用特点:
1. 当父类和子类都实现load函数时, 父类的load方法执行顺序要优先于子类
2. 当子类未实现load方法时, 不会调用父类load方法
3. 类中的load方法执行顺序要优先于类别(Category)
4. 当有多个类别(Category)都实现了load方法, 这几个load方法都会执行,
但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
5. 当然当有多个不同的类的时候,
每个类load 执行顺序与其在Compile Sources出现的顺序一致

initialize:
1.父类的initialize方法会比子类先执行
2.当子类未实现initialize方法时, 会调用父类initialize方法,
子类实现initialize方法时, 会覆盖父类initialize方法.
3. 当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
4. 由于是系统自动调用，也不需要再调用 [super initialize]

#pragma mark - 类的底层实现
【类的底层实现.h】
